#include "Eventfd.hpp"

#include <sys/eventfd.h>
#include <unistd.h>
#include <poll.h>

#include <iostream>

namespace xww
{
    Eventfd::Eventfd(EventfdCallback &&cb)
        : _eventfd(createEventfd()), _cb(std::move(cb)), _isStarted(false)
    {
    }

    Eventfd::~Eventfd()
    {
        close(_eventfd);
    }

    // 创建一个eventfd对象
    // eventfd是Linux内核提供的一种事件通知机制
    // 它可以用于线程间通信、进程间通信等场景
    // 它的主要作用是提供一个文件描述符，通过读写这个文件描述符
    // 来实现事件的通知和处理
    // eventfd的使用方式类似于管道，可以通过read和write操作来进行
    // 事件的通知和处理
    // eventfd的优点是效率高、性能好、易于使用
    // eventfd的缺点是只能在Linux系统上使用，不支持其他操作系统
    // eventfd的使用场景包括线程间通信、进程间通信、事件通知等
    // eventfd的使用方式是先创建一个eventfd对象，然后通过write
    // 操作来通知事件的发生，通过read操作来处理事件的通知
    void Eventfd::start()
    {
        struct pollfd pfd;
        pfd.fd = _eventfd;
        pfd.events = POLLIN;

        _isStarted = true;
        while (_isStarted)
        {
            int nready = poll(&pfd, 1, 6000);
            if (nready == -1 && errno == EINTR)
            {
                continue;
            }
            else if (nready == -1)
            {
                perror("Poll");
            }
            else if (nready == 0)
            {
                perror("Poll timeout");
            }
            else
            {
                handleReadEvent();
                if (_cb)
                {
                    _cb();
                }
            }
        }
    }

    void Eventfd::stop()
    {
        _isStarted = false;
    }

    int Eventfd::createEventfd()
    {
        int fd = eventfd(0, 0); // 创建一个eventfd对象
        if (fd < 0)
        {
            perror("Eventdf");
        }
        return fd;
    }

    // 处理读事件
    // 当有事件发生时，eventfd会通知应用程序
    // 应用程序通过read操作来读取事件的通知
    // 并执行相应的回调函数
    // 这里的回调函数是通过构造函数传入的
    // 回调函数的作用是处理事件的通知
    // 在这里，我们读取eventfd的值，并打印出来
    // eventfd的值表示有多少个事件发生了
    // 如果读取失败，则打印错误信息
    // 如果读取成功，则打印事件的数量
    // eventfd的值是一个64位无符号整数，表示有多少个事件发生了
    // 每次调用write操作都会将eventfd的值加1
    // 每次调用read操作都会将eventfd的值减1
    void Eventfd::handleReadEvent()
    {
        uint64_t howmany = 0;
        int ret = read(_eventfd, &howmany, sizeof(howmany));
        printf("\nhowmany : %ld\n", howmany);
        if (ret != sizeof(howmany))
        {
            perror("Read eventfd");
        }
    }

    // 唤醒事件
    // 通过write操作来通知事件的发生
    // 这里的事件是通过构造函数传入的回调函数来处理的
    // write操作会将eventfd的值加1
    // 每次调用write操作都会将eventfd的值加1
    // 每次调用read操作都会将eventfd的值减1
    // 如果write操作失败，则打印错误信息
    // 如果write操作成功，则表示事件的发生
    // 事件的发生会触发poll函数的返回
    // 从而执行handleReadEvent函数
    // 从而执行回调函数
    void Eventfd::wakeup()
    {
        uint64_t one = 1;
        int ret = write(_eventfd, &one, sizeof(one));
        if (ret != sizeof(one))
        {
            perror("Write eventfd");
        }
    }

} // end of namespace xww
